package cn.zyjblogs.sms.provider.tencent;

import cn.zyjblogs.sms.common.SmsRequest;
import cn.zyjblogs.sms.common.SmsResponse;
import cn.zyjblogs.sms.exception.SmsRuntimeException;
import cn.zyjblogs.sms.provider.AbstractSmsGranter;
import cn.zyjblogs.sms.provider.SmsGranter;
import cn.zyjblogs.sms.task.constant.ProviderType;
import cn.zyjblogs.sms.task.constant.TaskStatus;
import cn.zyjblogs.sms.task.dto.TaskResultDTO;
import cn.zyjblogs.starter.common.entity.dto.Kv;
import cn.zyjblogs.starter.common.utils.collect.Lists;
import cn.zyjblogs.starter.common.utils.string.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.baidubce.services.sms.model.SendMessageItem;
import com.baidubce.services.sms.model.SendMessageV3Response;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zhuyijun
 */
public class TenSmsHandleGranter extends AbstractSmsGranter {
    private static Logger log = LoggerFactory.getLogger(TenSmsHandleGranter.class);
    private static final ProviderType PROVIDER_TYPE = ProviderType.TENCENT;
    public TenSmsHandleGranter() {
        super(PROVIDER_TYPE);
    }
    public TenSmsHandleGranter(ProviderType providerType) {
        super(providerType);
    }
    private static final Map<String, String> ERROR_CODE_MAP = new HashMap<>(50);

    static {
        ERROR_CODE_MAP.put("1000", "发送成功");
        ERROR_CODE_MAP.put("1001", "sig 校验失败");
        ERROR_CODE_MAP.put("1002", "短信/语音内容中含有敏感词");
        ERROR_CODE_MAP.put("1003", "请求包体没有 sig 字段或 sig 为空");
        ERROR_CODE_MAP.put("1004", "请求包解析失败，通常情况下是由于没有遵守 API 接口说明规范导致的");
        ERROR_CODE_MAP.put("1006", "请求没有权限");
        ERROR_CODE_MAP.put("1007", "其他错误");
        ERROR_CODE_MAP.put("1008", "请求下发短信/语音超时");
        ERROR_CODE_MAP.put("1009", "请求 IP 不在白名单中");
        ERROR_CODE_MAP.put("1011", "不存在该 REST API 接口");
        ERROR_CODE_MAP.put("1012", "签名格式错误或者签名未审批");
        ERROR_CODE_MAP.put("1013", "下发短信/语音命中了频率限制策略");
        ERROR_CODE_MAP.put("1014", "模版未审批或请求的内容与审核通过的模版内容不匹配");
        ERROR_CODE_MAP.put("1015", "手机号在阻止列表库中，通常是用户退订或者命中运营商阻止列表导致的");
        ERROR_CODE_MAP.put("1016", "手机号格式错误");
        ERROR_CODE_MAP.put("1017", "请求的短信内容太长");
        ERROR_CODE_MAP.put("1018", "语音验证码格式错误");
        ERROR_CODE_MAP.put("1019", "sdk appId 不存在");
        ERROR_CODE_MAP.put("1020", "sdk appId 已禁用");
        ERROR_CODE_MAP.put("1021", "请求发起时间不正常，通常是由于您的服务器时间与腾讯云服务器时间差异超过10分钟导致的");
        ERROR_CODE_MAP.put("1022", "业务短信日下发条数超过设定的上限");
        ERROR_CODE_MAP.put("1023", "单个手机号30秒内下发短信条数超过设定的上限");
        ERROR_CODE_MAP.put("1024", "单个手机号1小时内下发短信条数超过设定的上限");
        ERROR_CODE_MAP.put("1025", "单个手机号日下发短信条数超过设定的上限");
        ERROR_CODE_MAP.put("1026", "单个手机号下发相同内容超过设定的上限");
        ERROR_CODE_MAP.put("1029", "营销短信发送时间限制");
        ERROR_CODE_MAP.put("1030", "不支持该请求");
        ERROR_CODE_MAP.put("1031", "套餐包余量不足");
        ERROR_CODE_MAP.put("1032", "个人用户没有发营销短信的权限");
        ERROR_CODE_MAP.put("1033", "欠费被停止服务");
        ERROR_CODE_MAP.put("1034", "群发请求里既有国内手机号也有国际手机号");
        ERROR_CODE_MAP.put("1036", "单个模板变量字符数超过12个");
        ERROR_CODE_MAP.put("1045", "不支持该地区短信下发");
        ERROR_CODE_MAP.put("1046", "调用群发 API 接口单次提交的手机号个数超过200个");
        ERROR_CODE_MAP.put("1047", "国际短信日下发条数被限制");
        ERROR_CODE_MAP.put("60008", "处理请求超时");
    }

    @Override
    public List<SmsResponse> sendSms(SmsRequest smsRequest) {
        SendSmsRequest sendSmsRequest = new SendSmsRequest();
        sendSmsRequest.setTemplateId(smsRequest.getTemplateCode());
        sendSmsRequest.setSignName(smsRequest.getSignName());
        sendSmsRequest.setSessionContext(String.valueOf(smsRequest.getTaskId()));
        sendSmsRequest.setSmsSdkAppId(smsRequest.getAppId());
        List<Kv> param = JSON.parseArray(smsRequest.getTemplateParams(), Kv.class);
        List<String> paramList = new ArrayList<>();
        for (Kv kv : param) {
            paramList.add((String) kv.getV());
        }
        sendSmsRequest.setTemplateParamSet(paramList.toArray(String[]::new));
        return getSmsResponse(smsRequest, sendSmsRequest);
    }


    private List<SmsResponse> getSmsResponse(SmsRequest smsRequest, SendSmsRequest sendSmsRequest) {

        SmsClient client = createClient(smsRequest);
        try {
            sendSmsRequest.setPhoneNumberSet(smsRequest.getTelNums().toArray(new String[0]));
            SendSmsResponse sendSmsResponse = client.SendSms(sendSmsRequest);
            return assembleSendSmsResponse(sendSmsResponse);
        } catch (TencentCloudSDKException e) {
            log.error("发送短信失败,错误码: {}  错误信息:{} 回调requestId: {}",e.getErrorCode(),e.getMessage(),e.getRequestId());
            List<String> telNum1 = smsRequest.getTelNums();
            List<SmsResponse> responses = new LinkedList<>();
            for (String phone : telNum1) {
                responses.add(SmsResponse.builder()
                        .code(e.getErrorCode())
                        .sendStatus(ProviderType.TENCENT.getTaskStatus(e.getErrorCode()))
                        .phoneNumber(phone)
                        .bizId(e.getRequestId())
                        .ext(smsRequest.getTaskId())
                        .message(ERROR_CODE_MAP.getOrDefault(e.getErrorCode(), e.getMessage()))
                        .build());
            }
            return responses;
        } catch (Exception e){
            log.error("发送短信失败 错误信息:{} ",e.getMessage());
            return Collections.emptyList();
        }
    }

    private List<SmsResponse> assembleSendSmsResponse(SendSmsResponse sendSmsResponse) {
        if (sendSmsResponse == null || sendSmsResponse.getSendStatusSet() == null) {
            return Collections.emptyList();
        }
        List<SmsResponse> responses = new LinkedList<>();
        SendStatus[] sendStatusSet = sendSmsResponse.getSendStatusSet();
        for (SendStatus sendStatus : sendStatusSet) {
            responses.add(SmsResponse.builder()
                    .code(sendStatus.getCode())
                    .phoneNumber(sendStatus.getPhoneNumber())
                    .bizId(sendStatus.getSerialNo())
                    .fee(sendStatus.getFee())
                    .sendStatus(ProviderType.TENCENT.getTaskStatus(sendStatus.getCode()))
                    .ext(sendStatus.getSessionContext())
                    .ext(sendSmsResponse.getRequestId())
                    .message(ERROR_CODE_MAP.getOrDefault(sendStatus.getCode(), sendStatus.getMessage()))
                    .build());
        }
        return responses;
    }

    @SneakyThrows
    public static SmsClient createClient(SmsRequest smsRequest)  {
        com.tencentcloudapi.common.Credential credential = new com.tencentcloudapi.common.Credential(smsRequest.getAccessKey(), smsRequest.getAccessSecret());
        if (!StringUtils.isEmpty(smsRequest.getEndPoint())){
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(smsRequest.getEndPoint());
            ClientProfile profile = new ClientProfile();
            profile.setHttpProfile(httpProfile);
            return new SmsClient(credential, smsRequest.getRegion(),profile);
        }
        return new SmsClient(credential, smsRequest.getRegion());
    }


    @Override
    public SmsGranter getGranter(ProviderType providerType) {
        if (PROVIDER_TYPE.equals(providerType)) {
            return this;
        }
        return null;
    }
}
